﻿// ===============================================================================
// Project Name        :    Gfw.BLL.Basic.Facilities
// Project Description :    
// ===============================================================================
// Class Name          :    Transfer
// Namespace:          :    Gfw.BLL.Basic.Facilities
// Class Version       :    v1.0.0.0
// Class Description   :    
// CLR Version:        :    4.0.30319.17626
//Author               :    lif
// Machine             :    ADICO-PC
// Create Time         :    2012/7/8 12:08:34
// Update Time         :    2012/7/8 12:08:34
// ===============================================================================
// Copyright © lif 2012 . All rights reserved.
// ===============================================================================

using System;
using Gfw.Infrastructure.ExceptionImpl;
using Gfw.Infrastructure.User;
using Gfw.Models.Account;
using Gfw.Models.Admin;
using Gfw.Repositories.Account;
using Gfw.Repository;
using Gfw.Infrastructure.Account;

namespace Gfw.Infrastructure.Facilities
{
    /// <summary>
    /// 转账，用户转用户（含担保交易）
    /// <para>客户转用户见Recharge类</para>
    /// </summary>
    public class TransferFacility : IFacility
    {
        #region Private Fields

        protected UsrUser _user;
        protected UsrUser _toUser;
        protected decimal _count;
        protected bool canActive = false;

        #endregion

        #region 无担保转账

        /// <summary>
        /// 构造函数初始化（for 无担保交易）
        /// </summary>
        /// <param name="user">发起（转出）用户</param>
        /// <param name="toUser">转入用户</param>
        /// <param name="count">转账金额</param>
        public TransferFacility(UsrUser user, UsrUser toUser, decimal count)
        {
            if (count <= 0)
                throw new GfwVerifyException("转账的参数不正确！");

            _count = count;
            _toUser = toUser;
            _user = user;
        }

        /// <summary>
        /// 会员转会员（for 无担保交易）
        /// </summary>
        /// <param name="unitOfWork"></param>
        public virtual void Execute(Repository.UnitOfWork unitOfWork = null)
        {
            try
            {
                if (unitOfWork != null)
                    throw new GfwException("当前事务只能作为原子事务，不允许与其它操作公用数据库事务。");
                if (_user == null)
                    throw new GfwVerifyException("登录超时！");
                if (_toUser == null)
                    throw new GfwVerifyException("转入帐户不存在！");
                if (_count <= 0)
                    throw new GfwVerifyException("转账的参数不正确！");

                UnitOfWork work = unitOfWork ?? new UnitOfWork();
                ActUserAccountinformationRepository accountRep = new ActUserAccountinformationRepository();

                var userAccount = accountRep.Get(_user.Id, work);
                if (userAccount == null)
                    throw new GfwVerifyException("转出用户不存在！");
                if (userAccount.ElectronicMoney < _count)
                    throw new GfwVerifyException("余额不足！");

                var toUserAccount = accountRep.Get(_toUser.Id, work);
                if (toUserAccount == null)
                    throw new GfwVerifyException("指定用户不存在！");

                userAccount.ElectronicMoney -= _count;
                toUserAccount.ElectronicMoney += _count;

                DateTime tradeDate = DateTime.Now;
                ActUserBargain4emoney userEhistory = new ActUserBargain4emoney()
                {
                    Id = Guid.NewGuid().ToString(),
                    Userid = _user.Id,
                    AwardSerialNo = "",
                    Balance = userAccount.ElectronicMoney,
                    Income = 0,
                    Outlay = _count,
                    Taxation = 0,
                    TaxationSerialNo = "",
                    TradeAbstract = "直接转出",
                    TradeType = (int)UserTradeTypeEnum.Out,
                    TradePattern = (int)TradePatternEnum.NonWarrant,
                    TradeDate = tradeDate,
                    ToUserId = _toUser.Id,
                    ToUserLoginName = _toUser.LoginName
                };
                ActUserBargain4emoney toUserEhistory = new ActUserBargain4emoney()
                {
                    Id = Guid.NewGuid().ToString(),
                    Userid = _toUser.Id,
                    AwardSerialNo = "",
                    Balance = toUserAccount.ElectronicMoney,
                    Income = _count,
                    Outlay = 0,
                    Taxation = 0,
                    TaxationSerialNo = "",
                    TradeAbstract = "直接转入",
                    TradeType = (int)UserTradeTypeEnum.In,
                    TradePattern = (int)TradePatternEnum.NonWarrant,
                    TradeDate = tradeDate,
                    ToUserId = _user.Id,
                    ToUserLoginName = _user.LoginName
                };

                accountRep.Update(userAccount, work);
                accountRep.Update(toUserAccount, work);
                ActUserBargain4emoneyRepository emoneyRep = new ActUserBargain4emoneyRepository();
                emoneyRep.Save(userEhistory, work);
                emoneyRep.Save(toUserEhistory, work);

                if (unitOfWork == null)
                    work.Commit();

                if (toUserAccount.Status == (int)UserStatusEnum.NotActive
                && toUserAccount.ElectronicMoney >= 560)
                {
                    canActive = true;
                }
            }
            catch (System.Exception ex)
            {
                throw new GfwVerifyException(ex.Message);
            }
        }

        #endregion



        #region 担保交易

        /// <summary>
        /// 担保：卖家转入中间方（for 担保交易【卖家】）
        /// </summary>
        /// <param name="unitOfWork"></param>
        /// <param name="user">发起（转出）用户</param>
        /// <param name="toUser">转入用户</param>
        /// <param name="count">转账金额</param>
        /// <param name="bankName">开户行（四大银行 + 财付通 + 支付宝）字典</param>
        /// <param name="bankCardNo">账号</param>
        /// <param name="bankUserName">开户名</param>
        public static void ExecuteWarrantOut(UsrUser user, UsrUser toUser, decimal count,
            string bankName, string bankCardNo, string bankUserName,
            Repository.UnitOfWork unitOfWork = null)
        {
            try
            {
                if (unitOfWork != null)
                    throw new GfwException("当前事务只能作为原子事务，不允许与其它操作公用数据库事务。");
                if (user == null)
                    throw new GfwVerifyException("登录超时！");
                if (toUser == null)
                    throw new GfwVerifyException("转入帐户不存在！");
                if (count <= 0)
                    throw new GfwVerifyException("转账的参数不正确！");


                UnitOfWork work = unitOfWork ?? new UnitOfWork();
                ActUserAccountinformationRepository accountRep = new ActUserAccountinformationRepository(); // 修改：用户账户信息表
                ActUserBargain4emoneyRepository emoneyRep = new ActUserBargain4emoneyRepository(); // 修改：用户电子币交易明细
                ActUserWarrantRepository warrantRep = new ActUserWarrantRepository(); // 修改：用户担保交易表

                var userAccount = accountRep.Get(user.Id, work);
                if (userAccount == null)
                    throw new GfwVerifyException("转出用户不存在！");
                if (userAccount.ElectronicMoney < count)
                    throw new GfwVerifyException("余额不足！");
                userAccount.ElectronicMoney -= count;

                DateTime tradeDate = DateTime.Now;
                ActUserBargain4emoney userEhistory = new ActUserBargain4emoney()
                {
                    Id = Guid.NewGuid().ToString(),
                    Userid = user.Id,
                    AwardSerialNo = "",
                    Balance = userAccount.ElectronicMoney,
                    Income = 0,
                    Outlay = count,
                    Taxation = 0,
                    TaxationSerialNo = "",
                    TradeAbstract = "担保转出",
                    TradeType = (int)UserTradeTypeEnum.Out,
                    TradePattern = (int)TradePatternEnum.Warrant,
                    TradeDate = tradeDate,
                    ToUserId = toUser.Id,
                    ToUserLoginName = toUser.LoginName,
                };


                ActUserWarrant userWarrant = new ActUserWarrant()
                {
                    Id = Guid.NewGuid().ToString(),
                    Userid = user.Id,
                    UserLoginName = user.LoginName,
                    ToUserId = toUser.Id,
                    ToUserLoginName = toUser.LoginName,
                    TradeDate = tradeDate,
                    BankName = bankName,
                    BankCardNo = bankCardNo,
                    BankUserName = bankUserName,
                    Tel = user.Tel,
                    Qq = user.Qq,
                    Money = count,
                    TransferOrWithdrawDate = null,
                    AckDate = null,
                    BankSerialNo = "",
                    Status = (int)WarrantStatusEnum.Progress,
                    TradeAbstract = "担保进行中，等待买家确认",
                };

                accountRep.Update(userAccount, work);
                emoneyRep.Save(userEhistory, work);
                warrantRep.Save(userWarrant, work);

                if (unitOfWork == null)
                    work.Commit();
            }
            catch (System.Exception ex)
            {
                throw new GfwVerifyException(ex.Message);
            }
        }

        /// <summary>
        /// 担保：中间方转入买家（for 担保交易【卖家】）
        /// </summary>
        /// <param name="userID">发起（转出）用户ID</param>
        /// <param name="userLoginName">发起（转出）用户登录名</param>
        /// <param name="toUserID">转入用户ID</param>
        /// <param name="tradeDate">担保时间</param>
        /// <param name="unitOfWork"></param>
        public static void ExecuteWarrantIn(string userID, string userLoginName, string toUserID, DateTime tradeDate,
            Repository.UnitOfWork unitOfWork = null)
        {
            try
            {
                if (unitOfWork != null)
                    throw new GfwException("当前事务只能作为原子事务，不允许与其它操作公用数据库事务。");
                if(string.IsNullOrEmpty(userID))
                    throw new GfwVerifyException("转出用户ID错误！");
                if(string.IsNullOrEmpty(toUserID))
                    throw new GfwVerifyException("转入用户ID错误！");


                UnitOfWork work = unitOfWork ?? new UnitOfWork();
                ActUserAccountinformationRepository accountRep = new ActUserAccountinformationRepository(); // 修改：用户账户信息表
                ActUserBargain4emoneyRepository emoneyRep = new ActUserBargain4emoneyRepository(); // 修改：用户电子币交易明细
                ActUserWarrantRepository warrantRep = new ActUserWarrantRepository(); // 修改：用户担保交易表


                ActUserWarrant userWarrant = warrantRep.GetWarrantByBothUserIDAndTradeDate(userID,
                    toUserID, tradeDate, (int)WarrantStatusEnum.Transfer, work);
                if (userWarrant == null || userWarrant.TransferOrWithdrawDate == null)
                    throw new GfwVerifyException("没有查询到相关担保信息！");
                if (userWarrant.Status != (int)WarrantStatusEnum.Transfer)
                    throw new GfwVerifyException("不能进行已确认操作！");

                DateTime ackDate = DateTime.Now;
                userWarrant.AckDate = ackDate;
                userWarrant.Status = (int)WarrantStatusEnum.Acknowledge;
                userWarrant.TradeAbstract = "卖家已确认，担保完成";


                var toUserAccount = accountRep.Get(toUserID, work);
                if(toUserAccount == null)
                    throw new GfwVerifyException("指定用户不存在！");
                toUserAccount.ElectronicMoney += userWarrant.Money;


                ActUserBargain4emoney toUserEhistory = new ActUserBargain4emoney()
                {
                    Id = Guid.NewGuid().ToString(),
                    Userid = toUserID,
                    AwardSerialNo = "",
                    Balance = toUserAccount.ElectronicMoney,
                    Income = userWarrant.Money,
                    Outlay = 0,
                    Taxation = 0,
                    TaxationSerialNo = "",
                    TradeAbstract = "担保转入",
                    TradeType = (int)UserTradeTypeEnum.In,
                    TradePattern = (int)TradePatternEnum.Warrant,
                    TradeDate = ackDate,
                    ToUserId = userID,
                    ToUserLoginName = userLoginName,
                };

                warrantRep.Update(userWarrant, work);
                accountRep.Update(toUserAccount, work);
                emoneyRep.Save(toUserEhistory, work);


                if (unitOfWork == null)
                    work.Commit();

                //如果用户没有激活，则需要激活用户
                //激活用户，没有做强制性认证
                if (toUserAccount.Status == (int)UserStatusEnum.NotActive
                    && toUserAccount.ElectronicMoney >= 560)
                {
                    ActiveUserFacility active = new ActiveUserFacility(toUserAccount.Userid);
                    active.Execute();
                }
            }
            catch (System.Exception ex)
            {
                throw new GfwVerifyException(ex.Message);
            }
        }

        /// <summary>
        /// 担保：买家撤销，返币给卖家（for 担保交易【买家 | 系统】）
        /// </summary>
        /// <param name="buyerID">买家ID</param>
        /// <param name="buyerLoginName">买家登录名</param>
        /// <param name="toSellerID">卖家ID</param>
        /// <param name="tradeDate">担保时间</param>
        /// <param name="unitOfWork"></param>
        public static void ExecuteWarrantReturn(string buyerID, string buyerLoginName, string toSellerID,
            DateTime tradeDate, Repository.UnitOfWork unitOfWork = null)
        {
            try
            {
                if (unitOfWork != null)
                    throw new GfwException("当前事务只能作为原子事务，不允许与其它操作公用数据库事务。");
                if (string.IsNullOrEmpty(buyerID))
                    throw new GfwVerifyException("转入用户ID错误！");
                if (string.IsNullOrEmpty(toSellerID))
                    throw new GfwVerifyException("转出用户ID错误！");


                UnitOfWork work = unitOfWork ?? new UnitOfWork();
                ActUserAccountinformationRepository accountRep = new ActUserAccountinformationRepository(); // 修改：用户账户信息表
                ActUserBargain4emoneyRepository emoneyRep = new ActUserBargain4emoneyRepository(); // 修改：用户电子币交易明细
                ActUserWarrantRepository warrantRep = new ActUserWarrantRepository(); // 修改：用户担保交易表


                ActUserWarrant userWarrant = warrantRep.GetWarrantByBothUserIDAndTradeDate(toSellerID, 
                    buyerID, tradeDate, (int)WarrantStatusEnum.Progress, work);
                if (userWarrant == null)
                    throw new GfwVerifyException("没有查询到相关担保信息！");
                if (userWarrant.Status != (int)WarrantStatusEnum.Progress &&
                    userWarrant.Status != (int)WarrantStatusEnum.Transfer)
                    throw new GfwVerifyException("不能进行撤单操作！");

                DateTime withdrawDate = DateTime.Now;
                userWarrant.TransferOrWithdrawDate = withdrawDate;
                switch (userWarrant.Status)
                {
                    case (int)WarrantStatusEnum.Progress:
                        userWarrant.TradeAbstract = "买家撤单，返还卖家";
                        break;
                    case (int)WarrantStatusEnum.Transfer:
                        userWarrant.TradeAbstract = "担保超期，返还卖家";
                        break;
                    default:
                        userWarrant.TradeAbstract = "担保撤销，返还卖家";
                        break;
                }
                userWarrant.Status = (int)WarrantStatusEnum.Return;


                var toSellerAccount = accountRep.Get(toSellerID, work);
                if (toSellerAccount == null)
                    throw new GfwVerifyException("指定用户不存在！");
                toSellerAccount.ElectronicMoney += userWarrant.Money;


                ActUserBargain4emoney toSellerEhistory = new ActUserBargain4emoney()
                {
                    Id = Guid.NewGuid().ToString(),
                    Userid = toSellerID,
                    AwardSerialNo = "",
                    Balance = toSellerAccount.ElectronicMoney,
                    Income = userWarrant.Money,
                    Outlay = 0,
                    Taxation = 0,
                    TaxationSerialNo = "",
                    TradeAbstract = userWarrant.TradeAbstract,
                    TradeType = (int)UserTradeTypeEnum.In,
                    TradePattern = (int)TradePatternEnum.Warrant,
                    TradeDate = withdrawDate,
                    ToUserId = buyerID,
                    ToUserLoginName = buyerLoginName,
                };

                warrantRep.Update(userWarrant, work);
                accountRep.Update(toSellerAccount, work);
                emoneyRep.Save(toSellerEhistory, work);


                if (unitOfWork == null)
                    work.Commit();
            }
            catch (System.Exception ex)
            {
                throw new GfwVerifyException(ex.Message);
            }
        }

        #endregion
    }
}
